package hyl.base.cache2;

import java.util.concurrent.ConcurrentLinkedDeque;

import hyl.core.MyFun;
import hyl.core.run.MyTimer;

public class ExTokenFactory {
	private ConcurrentLinkedDeque<ExToken> tokens = new ConcurrentLinkedDeque<>();
	//为什么要用定时任务, 
	//为了自动删除过期的令牌
	// 令牌即使不get 也会自动删除 ,确保令牌库不会过大
	MyTimer mt = MyTimer.getInstance("过期令牌", 16);
	int _过期毫秒 =60000; // 60000; // 一分钟后令牌自动过期

//	public static void main(String[] args) {
//		ExTokenFactory etl = new ExTokenFactory();
//		etl.add(new ExToken("1",7000));
//		MyDate.sleeps(1);
//		etl.add(new ExToken("2"));
//		MyDate.sleeps(1);
//		etl.add(new ExToken("3"));
//		MyDate.sleeps(1);
//		etl.show();
//		etl.add(new ExToken("4"));
//		MyDate.sleeps(1);
//		etl.add(new ExToken("5"));
//		MyDate.sleeps(1);
//		etl.add(new ExToken("6"));
//		MyDate.sleeps(1);
//		etl.show();
//		etl.add(new ExToken("7"));
//		MyDate.sleeps(1);
//		etl.add(new ExToken("8"));
//		MyDate.sleeps(2);		
//		etl.show();
//		MyDate.sleeps(2);		
//		etl.show();
//	}
	public ExTokenFactory() {
		mt.start(() -> {
			// System.out.println("开始清除");
			remove过期令牌();
		}, _过期毫秒);
	}

	public ExTokenFactory(int 过期毫秒) {
		_过期毫秒 = 过期毫秒;
		mt.start(() -> {
			// System.out.println("开始清除");
			remove过期令牌();
		}, _过期毫秒);
	}

	void remove过期令牌() {
		// 求稳不求快
		long now = MyFun.getMs();
		// foreach 循环实际上是用的 iterator 迭代器迭代
//		byte[] flag = new byte[1];
		tokens.forEach((e) -> {
			// System.out.println("---" + e);
//			if (flag[0] == 1) {
//				tokens.remove(e);
//				return;
//			}
			if (now > e.stamp + e.ms过期时长 || e.getI可用次数() == 0) {
				// System.out.println("---"+e.token);
				tokens.remove(e);
				e = null;
//				flag[0] = 1;// 只要当前过期,后续的一定过期
			}
		});
		// show();
	}

	/**
	 * 
	 * 只可以使用一次 默认一分钟过期
	 * 
	 * @return
	 */
	public ExToken createAdd() {
		ExToken etk = new ExToken(_过期毫秒);
		tokens.addFirst(etk);
		return etk;
	}
	/**
	 * 一般用于测试场景 默认3秒过期
	 * @param 指定令牌
	 * @return
	 */
	public ExToken createAdd(String 指定令牌) {
		ExToken etk = new ExToken(指定令牌);
		tokens.addFirst(etk);
		return etk;
	}
	/**
	 * 自定义过期时间
	 * 
	 * 只可以使用一次 
	 * @param 过期毫秒
	 * @return
	 */
	public ExToken createAdd(int 过期毫秒) {
		ExToken etk = new ExToken(过期毫秒);
		tokens.addFirst(etk);
		return etk;
	}

	// 最新的插入到最上面
	public void add(ExToken token) {
		tokens.addFirst(token);
	}

	private synchronized void remove(ExToken token) {
		tokens.remove(token);
		token = null;
	}

	public boolean contain(String token) {
		if (MyFun.isEmpty(token))
			return false;
		for (ExToken item : tokens) {
			if (item.id.equals(token)) {
				if (item.is有效()) {	
					return true;
				}else {//无效的token,直接销毁
					remove(item);
					return false;
				}
			}
		}
		return false;
	}
	/**
	 * 检查是否存在,,同时标记使用一次
	 * @param token
	 * @return
	 */
	public boolean contain_1(String token) {
		if (MyFun.isEmpty(token))
			return false;
		for (ExToken item : tokens) {
			if (item.id.equals(token)) {
				if (item.is有效()){	
					//int i=
					item.exec();
					//System.out.println(i);
					return true;
				} else {//无效的token,直接销毁
					remove(item);
					return false;
				}
			}
		}
		return false;
	}
	/**
	 * 过期的token 不用取出 直接扔掉
	 * 
	 * @param token
	 * @return
	 */
	public ExToken get(String token) {
		if (MyFun.isEmpty(token))
			return null;
		for (ExToken item : tokens) {
			if (item.id.equals(token)) {
				if (item.is有效()) {
					return item;
				}else {//无效的token,直接销毁
					remove(item);
					return null;
				}
			}
		}
		return null;
	}
	public ExToken get2(String token) {
		if (MyFun.isEmpty(token))
			return null;
		for (ExToken item : tokens) {
			if (item.id.equals(token)) {
				if (item.is有效()) {
					item.exec();
					return item;
				}else {
					remove(item);
					return null;
				}
			}
		}
		return null;
	}
//
//	public ExToken is有效(String token) {
//		ExToken et = get(token);
//		if (et == null)
//			return null;
//		if (et.is可用())
//			return et;
//		remove(token);
//		return null;
//
//	}

	public synchronized void remove(String token) {
//		Iterator<ExToken> iter = tokens.iterator();
//	    while (iter.hasNext()) {
//	    	ExToken item = iter.next();
//	    	if (item.token.equals(token)) {
//				tokens.remove(item);
//				return;
//			}		
//	    }	    
		if (MyFun.isEmpty(token))
			return;
		for (ExToken item : tokens) {
			if (item.id.equals(token)) {
				remove(item);
				return;
			}
		}
	}

	public void show() {
		long now = MyFun.getMs();
		tokens.forEach((e) -> {
			if (now > e.stamp + e.ms过期时长 || e.getI可用次数() == 0) {
				// System.out.println("---"+e.token);
				remove(e);
				return;
			}
			System.out.println(e);
		});
	}

	// 不要实现 getAll 没有意义 因为 每次get 都要判断是否有效
}
